package thread;

/**
 * Creared with IntelliJ IDEA.
 * Description:实现阻塞队列及生产者消费者模型
 * User:yxd
 * Date:2022-03-29
 * Time:0:23
 */
class MyQueue{
    //存放数据的数组
    private int[] nums = new int[1000];
    //数组内的有效个数
    private int size = 0;
    //队首下标
    private int head = 0;
    //队尾下标
    private int tail = 0;
    private Object locker = new Object();
    //我们发现整个代码都在操作公共变量那么就可以直接够整个方法加锁了
    public void put(int val) throws InterruptedException {
        synchronized (locker){
            if(size == nums.length){

                locker.wait();//直接让这个线程陷入阻塞,直至有效元素不再满为止

                //return;//队列满
            }
            //把新的元素放到tail位置,表示入了一个新的元素
            nums[tail] = val;

            tail ++;
            //处理tail到达末尾的情况
            if(tail >= nums.length){
                tail = 0;
            }//也可以写为 tail = tail % nums.length;
            size ++;//有效个数增加
            locker.notify();//put成功之后就可以唤醒take的wait操作
        }

    }
    public int take() throws InterruptedException {
        synchronized (locker){
            if(size == 0){

                locker.wait();//直接让这个线程陷入阻塞,直至有效元素不再空为止

                //return -1;
            }
            //取出队首的元素
            int ret = nums[head];
            head ++;
            if(head >= nums.length){
                head = 0;
            }
            size --;
            locker.notify();//take成功之后就可以唤醒put中的阻塞操作   彼此唤醒对方的锁
            return ret;
        }

    }
}
public class Demo22 {
    private static MyQueue queue = new MyQueue();

    public static void main(String[] args) {
        //简单实现一个生产者消费者模型
        Thread producter = new Thread(()->{
            int num = 0;
            while(true){
                try {
                    System.out.println("生产了" + num);
                    queue.put(num);
                    num ++;
                    //Thread.sleep(500);
                    //当生产者生产的慢了消费者就得跟着生产者的步伐走
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producter.start();
        Thread customer = new Thread(()->{
            while(true){
                try {
                    int num = queue.take();
                    System.out.println("消费了" + num);
                    Thread.sleep(500);//当消费者者慢了生产者一瞬间可以生产很多,但消费者还是慢慢的消费切不会崩溃
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        customer.start();
    }
}
